#include "decode.hpp"
#include <cstring>

namespace fur
{
   uint16_t Decode::get_number(BitInput & bitinput) throw()
   {
      uint16_t bits;
      uint16_t bitfield = bitinput.getbits_16() & 0xfffe;
      bits = len[bitfield];
      bitinput.addbits(bits);
      uint32_t n = position[bits] + ((bitfield - length[bits - 1]) >> (16 - bits));
      if (n >= maxnumber)
	 n = 0;
      return number[n];
   }

   void Decode::make_table(uint8_t * lengthtable, int size) throw()
   {
      int lengthcount[16];
      int tmp[16];
      int i;
      uint32_t m;
      uint32_t n = 0;
      memset(lengthcount, 0, sizeof(lengthcount));
      memset(number, 0, sizeof(number));
      for (i = 0; i < size; ++i)
      {
	 ++lengthcount[lengthtable[i]];
      }
      lengthcount[0] = 0;
      tmp[0] = 0;
      position[0] = 0;
      length[0] = 0;
      for (i = 1; i < 16; ++i)
      {
	 n = 2 * (n + lengthcount[i]);
	 m = n << (15 - i);
	 if (m > 0xffff)
	    m = 0xffff;
	 length[i] = (uint16_t) m;
	 tmp[i] = position[i] = position[i - 1] + lengthcount[i - 1];
      }
      for (i = 0; i < size; ++i)
      {
	 if (lengthtable[i] != 0)
	 {
	    number[tmp[lengthtable[i]&0xf]++] = i;
	 }
      }
      maxnumber = size;
      for (i = 0; i < 15; ++i)
      {
	 memset(len + length[i], i + 1, length[i+1] - length[i]);
      }
      if (len[15] != 0xffff )
	 memset(len + length[15], 15, 0xffff - length[15]);
   }
} // end of namespace fur

